using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEngine;

namespace TripleMatch
{
    public static class Util 
    {
        public static List<int> GetRangeList(List<int> _inputList, int _outputNum)
        {
            if (_outputNum > _inputList.Count) return null;
            else
            {
                List<int> resultList = new List<int>(_inputList);
                for (int i = 0; i < _inputList.Count - _outputNum; i++)
                {
                    int nextRangeMax = resultList.Count - 1;
                    int kickIndex = UnityEngine.Random.Range(0, nextRangeMax);
                    resultList.RemoveAt(kickIndex);
                }

                return resultList;
            }
        }

        public static List<T> LoadCsvFileList<T>(string filePath, int dropCount = 1)
        {
            List<T> dataList = new List<T>();
            if (!File.Exists(filePath))
            {
                return dataList;
            }
            string[] lines = File.ReadAllLines(filePath);
            if (lines.Length < dropCount)
            {
                Debug.LogError("lines.Length < dropCount filePath = " + filePath);
                return null;
            }

            string headerLine = lines[0];
            //parse variable index
            string[] header_params = headerLine.Split(',');
            List<string> headerParamList = new List<string>();

            Dictionary<FieldInfo, int> dicParamIndex = new Dictionary<FieldInfo, int>();
            FieldInfo[] fieldInfos = typeof(T).GetFields();
            for (int index = 0; index < header_params.Length; index++)
            {
                var fieldName = header_params[index];
                if (headerParamList.Contains(fieldName))
                {
                    Debug.LogError(string.Format("headerParamList.Contains({0}) filePath = {1}", fieldName, filePath));
                    return null;
                }
                for (int i = 0; i < fieldInfos.Length; i++)
                {
                    FieldInfo fieldInfo = fieldInfos[i];
                    if (fieldInfo.Name == fieldName)
                    {
                        if (dicParamIndex.ContainsKey(fieldInfo))
                        {
                            Debug.LogError("dicParamIndex.ContainsKey(fieldInfo) " + fieldInfo.Name);
                        }
                        dicParamIndex.Add(fieldInfo, index);
                        break;
                    }
                }
            }

            for (int i = dropCount; i < lines.Length; i++)
            {
                var line = lines[i].Remove("\r").Remove("\n");
                if (string.IsNullOrEmpty(line)) { continue; }
                string[] dataParams = line.Split(',');
                object csvData = Activator.CreateInstance(typeof(T));
                foreach (var param in dicParamIndex)
                {
                    //if (!string.IsNullOrEmpty(dataParams[param.Value]))
                    try
                    {
                        param.Key.SetValue(csvData, param.Key.GetFieldValue(dataParams[param.Value]));
                    }
                    catch
                    {
                        continue;
                    }
                }
                dataList.Add((T)csvData);
            }

            return dataList;
        }

        public static void SaveCsvFileList<T>(string filePath, List<T> dataList)
        {
            try
            {
                if (File.Exists(filePath))
                {
                    File.Delete(filePath);
                    //File.Create(filePath);
                }

                FileStream fileStream = File.Open(filePath, FileMode.OpenOrCreate);
                StreamWriter streamWriter = new StreamWriter(fileStream);

                FieldInfo[] fieldInfos = typeof(T).GetFields();
                //header
                foreach (var fieldInfo in fieldInfos)
                {
                    streamWriter.Write(fieldInfo.Name);
                    streamWriter.Write(',');
                }
                streamWriter.Write('\n');

                foreach (var data in dataList)
                {
                    foreach (var fieldInfo in fieldInfos)
                    {
                        streamWriter.Write(fieldInfo.GetValue(data).ToString());
                        streamWriter.Write(',');
                    }
                    streamWriter.Write('\n');
                }
                streamWriter.Close();
                fileStream.Close();
            }
            catch (Exception ex)
            {
                Debug.LogError(ex.Message);
            }
        }
    }

    public static class DataUtils
    {
        public static string Remove(this string str, string removeStr)
        {
            if (string.IsNullOrEmpty(str))
            {
                return str;
            }
            else
            {
                return str.Replace(removeStr, "");
            }
        }

        public static object GetFieldValue(this System.Reflection.FieldInfo fieldInfo, string strValue)
        {
            object ret = 0;
            if (fieldInfo.FieldType == typeof(System.Int32))
            {
                ret = strValue.ParseInt();
            }
            else if (fieldInfo.FieldType == typeof(System.UInt32))
            {
                ret = strValue.ParseUInt();
            }
            else if (fieldInfo.FieldType == typeof(System.Single))
            {
                ret = strValue.ParseFloat();
            }
            else if (fieldInfo.FieldType == typeof(System.String))
            {
                ret = strValue;
            }
            return ret;
        }

        public static int ParseInt(this string strValue)
        {
            try
            {
                string fixedStr = string.IsNullOrEmpty(strValue) ? strValue : strValue.Remove(" ");
                if (string.IsNullOrEmpty(fixedStr))
                {
                    return 0;
                }
                else
                {
                    return System.Convert.ToInt32(fixedStr);
                }
            }
            catch (Exception ex)
            {
                Debug.LogError("ex.Message = " + ex.Message);
                Debug.LogError("strValue = " + strValue);
            }
            return 0;
        }

        public static uint ParseUInt(this string strValue)
        {
            string fixedStr = string.IsNullOrEmpty(strValue) ? strValue : strValue.Remove(" ");
            if (string.IsNullOrEmpty(fixedStr))
            {
                return 0;
            }
            else
            {
                return System.Convert.ToUInt32(fixedStr);
            }
        }

        public static float ParseFloat(this string strValue)
        {
            try
            {
                string fixedStr = string.IsNullOrEmpty(strValue) ? strValue : strValue.Remove(" ");
                if (string.IsNullOrEmpty(fixedStr))
                {
                    return 0;
                }
                else
                {
                    return System.Convert.ToSingle(fixedStr);
                }
            }
            catch (Exception ex)
            {
                Debug.LogError("ex.Message = " + ex.Message);
                Debug.LogError("strValue = " + strValue);
            }
            return 0;
        }


        public static T ParseEnum<T>(string strValue)
        {
            try
            {
                T ret = (T)System.Enum.Parse(typeof(T), strValue);
                return ret;
            }
            catch (Exception ex)
            {
                Debug.LogError("ParseEnum Failed! T = " + typeof(T).Name + " strValue = " + strValue
                    + "\n" + ex.Message);
                throw ex;
            }
            T ret2 = default(T);
            return ret2;
        }
    }
}
